package com.h2.ref.server.proxy;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ProxyProvider {
   
   public void proxy(String method, String host,
         String proxyPath, Map<String, String> hashtable,
         Integer defaultTimeout, String proxyHost, String proxyPort,
         String encoding,
         Boolean keepHeaders, Boolean rewriteHost,
         HttpServletRequest request, HttpServletResponse response) {
      
      ProxyUtils.setTimeout(defaultTimeout);
      ProxyUtils.setProxy(proxyHost, proxyPort);
      
      //headers
      Map<String, String> headers =
         ProxyUtils.getHeaders(request);
      if (keepHeaders) {
         if (rewriteHost) {
            headers.remove("host");
            headers.remove("Host");
            headers.remove("HOST");
            headers.put("Host", ProxyUtils.getHostInfo(host));
         }
//         if ("false".equals(disableAcceptEncoding)) {
//            headers.remove("ACCEPT-ENCODING");
//         }
      }
      try {
         if ("GET".equalsIgnoreCase(method)) {
            if (proxyPath.toUpperCase().startsWith("HTTPS")) {
               throw new UnsupportedOperationException("SSL not implemented yet");
            }
            else {
               proxyGet(proxyPath, headers, encoding, request, response);
            }
         }
         else {
            throw new UnsupportedOperationException("Only GET supported");
         }
      } catch (IOException exp) {
         exp.printStackTrace();
      }
   }
   
   public void proxyGet(String proxyPath, Map<String, String> headers,
         String encoding,
         HttpServletRequest request,
         HttpServletResponse response) throws IOException {
      
      URLConnection connection = null;
      InputStream input = null;
      BufferedOutputStream bufferedOutputStream = null;
      try {
         URL url = new URL(proxyPath);
         connection = url.openConnection();
         connection.setDoInput(true);
         connection.setUseCaches(false);
         if (headers != null) {
            for (Entry<String, String> entry : headers.entrySet()) {
               connection.setRequestProperty(entry.getKey(),
                     entry.getValue());
            }
         }
      } catch (Exception exception) {
         ProxyUtils.getMessage(proxyPath, exception);
      }
      
      Integer responseCode = null;
      try {
         
         if (connection instanceof HttpURLConnection) {
            HttpURLConnection httpurlconnection =
               (HttpURLConnection) connection;
            responseCode = httpurlconnection.getResponseCode();
            response.setStatus(responseCode);
         }
         String contentType = connection.getContentType();
         if (contentType != null && encoding != null) {
            contentType = ProxyUtils.rewriteEncoding(contentType, encoding);
         }
         if (contentType != null) {
            response.setContentType(contentType);
         }
         else {
            contentType = "";
         }
         String incomingEncoding = connection.getContentEncoding();
         if (headers != null) {
            ProxyUtils.rewriteHeaders(connection.getHeaderFields(), response);
         }
         if (incomingEncoding == null) {
            incomingEncoding = "";
         }
         
         try {
            if (incomingEncoding.indexOf("gzip") >= 0) {
               input = new GZIPInputStream(connection.getInputStream());
            }
            else {
               input = new BufferedInputStream(connection.getInputStream());
            }
               
            bufferedOutputStream = new BufferedOutputStream(
                  response.getOutputStream());
            int i;
            while ((i = input.read()) >= 0) {
               bufferedOutputStream.write(i);
            }
         } catch (Exception exception2) {
            ProxyUtils.sendError(response, responseCode,
                  ProxyUtils.getMessage(proxyPath, exception2));
         }
      } catch (Exception exception1) {
         ProxyUtils.sendError(response, responseCode,
               ProxyUtils.getMessage(proxyPath, exception1));
      }
      if (input != null) {
         try {
            input.close();
         } catch (IOException exp) {
            exp.printStackTrace();
         }
      }
         
      if (bufferedOutputStream != null) {
         try {
            bufferedOutputStream.flush();
            bufferedOutputStream.close();
         } catch (IOException exp) {
            exp.printStackTrace();
         }
      }
   }

}
